<template>
	<view
		:class="{
			hairline: hairline,
			'box-shadow': boxShadow,
		}"
		:hover-class="disabled ? 'none' : hoverClass"
		:hover-stay-time="80"
		:hover-stop-propagation="hoverStopPropagation"
		:style="[setButtonStyle, disabled ? { opacity: opacity } : null]"
		class="my-button"
		@click="handleBtnClick"
		@longpress="handleLongPress"
	>
		<slot></slot>
	</view>
</template>

<script>
import { endUnitReg, endWithRpxOrUpxReg, strToNumReg } from "@/utils/reg.js"; // 引入用到的正则表达式
import colorInfo from "@/utils/color.js"; // 引入主题色配置
import { debounce, throttle } from "lodash";

export default {
	name: "my-button",
	props: {
		// 圆角
		borderRadius: {
			type: [Number, String],
			default: "24",
		},
		// 背景色
		background: {
			type: String,
			default: "",
		},
		// 字体颜色
		color: {
			type: String,
			default: "",
		},
		// 字体大小
		fontSize: {
			type: [Number, String],
			default: "28",
		},
		// 宽度
		width: {
			type: [Number, String],
			default: "100%",
		},
		// 高度
		height: {
			type: [Number, String],
			default: "96",
		},
		// 是否显示边框
		border: {
			type: Boolean,
			default: false,
		},
		// 是否使用0.5px边框
		hairline: {
			type: Boolean,
			default: false,
		},
		// 边框颜色
		borderColor: {
			type: String,
			default: "",
		},
		// 字重
		fontWeight: {
			type: [Number, String],
			default: "500",
		},
		// 行高
		lineHeight: {
			type: [Number, String],
			default: "normal",
		},
		// 点击态
		hoverClass: {
			type: String,
			default: "u-hover-class",
		},
		// 是否阻止祖先节点的点击态
		hoverStopPropagation: {
			type: Boolean,
			default: true,
		},
		// 是否节流
		throttle: {
			type: Boolean,
			default: false,
		},
		// 节流时间
		throttleTime: {
			type: [Number, String],
			default: 1000,
		},
		// 节流是否立即触发
		throttleImmediate: {
			type: Boolean,
			default: true,
		},
		// 是否防抖
		debounce: {
			type: Boolean,
			default: true,
		},
		// 防抖时间
		debounceTime: {
			type: [Number, String],
			default: 300,
		},
		// 防抖是否立即触发
		debounceImmediate: {
			type: Boolean,
			default: true,
		},
		// 是否禁用按钮
		disabled: {
			type: Boolean,
			default: false,
		},
		// 禁用按钮整体的透明度
		opacity: {
			type: [Number, String],
			default: "0.7",
		},
		// 按钮左右padding
		padding: {
			type: [Number, String],
			default: "32",
		},
		// 是否开启主题渐变色
		themeGradientColor: {
			type: Boolean,
			default: false,
		},
		// 是否需要按钮投影
		boxShadow: {
			type: Boolean,
			default: false,
		},
		// 自定义样式（因为uView2.0全局混入了customStyle的props，所以不能起一样的名字）
		currentStyle: {
			type: Object,
			default() {
				return {};
			},
		},
	},
	computed: {
		// 设置按钮样式
		setButtonStyle({
			width,
			height,
			borderRadius,
			fontSize,
			fontWeight,
			lineHeight,
			padding,
			border,
			currentStyle,
			setColor,
			setBackground,
			setBorderColor,
			setBorderRadius,
			$utils,
		}) {
			let styleObj = {
				width: $utils.addUnit(width),
				height: $utils.addUnit(height),
				borderRadius: $utils.addUnit(borderRadius),
				color: setColor,
				background: setBackground,
				fontSize: $utils.addUnit(fontSize),
				fontWeight: fontWeight,
				lineHeight: lineHeight,
				"--btn-border-color": setBorderColor,
				"--btn-border-radius": setBorderRadius,
				"--btn-border-width": border ? "1px" : "0px",
			};
			// 如果宽度设置auto，自动填充左右padding
			if ($utils.addUnit(width) === "auto") {
				styleObj.paddingLeft = $utils.addUnit(padding);
				styleObj.paddingRight = $utils.addUnit(padding);
			}
			// 返回对应的样式
			return Object.assign(styleObj, currentStyle);
		},
		// 设置背景色
		setBackground({ border, background, themeGradientColor }) {
			// 无边框并且显示渐变背景色情况下,有背景色就显示传过来的背景色，否则显示主题渐变色
			if (!border && themeGradientColor) {
				return !background ? colorInfo.themeGradientColor : background;
			}
			// 无边框的情况下,有背景色就显示传过来的背景色，否则显示主题色
			if (!border) return !background ? colorInfo.themeColor : background;
			// 有边框的情况下，有背景色就显示传过来的背景色，否则显示透明色
			return !background ? "rgba(0,0,0,0)" : background;
		},
		// 设置边框颜色
		setBorderColor({ border, borderColor }) {
			// 无边框的情况下,显示透明色
			if (!border) return "rgba(0,0,0,0)";
			// 有边框的情况下，有边框颜色就显示传过来的边框颜色，否则显示主题色
			return !borderColor ? colorInfo.themeColor : borderColor;
		},
		// 设置文字颜色
		setColor({ border, color }) {
			// 无边框的情况下,有文字颜色就显示传过来的文字颜色，否则把文字设置成白色
			if (!border) return !color ? "#fff" : color;
			// 有边框的情况下,有文字颜色就显示传过来的文字颜色，否则把文字设置成主题色
			return !color ? colorInfo.themeColor : color;
		},
		// 设置圆角
		setBorderRadius({ borderRadius, border, hairline }) {
			// 不显示边框或者圆角没值的情况下，或者特殊情况下props接收的值为true，圆角设置成0px
			if (!border || !borderRadius || borderRadius === true) return "0px";
			// 将圆角转换成字符串类型，并去掉所有空格
			borderRadius = String(borderRadius).replace(/\s+/g, "");
			// 提取所有数字部分，匹配到的话是个数组，匹配不到是null
			const matchList = borderRadius.match(strToNumReg);
			// console.log(matchList);
			// 匹配不到，或者包含auto，全部取0px
			if (!matchList || borderRadius.includes("auto")) return "0px";
			// 匹配到了就取数组最后一个，并转换成Number类型
			let matchVal = +matchList[matchList.length - 1];
			// console.log(matchVal);
			// 判断字符串是否以rpx、upx结尾，并拼接上px
			if (endWithRpxOrUpxReg.test(borderRadius)) {
				matchVal = uni.upx2px(matchVal) * (hairline ? 2 : 1); // 如果是0.5px边框因为使用了scale(0.5)，要乘以2
				borderRadius = matchVal + "px";
				// console.log("以rpx或者upx结尾按钮圆角", borderRadius);
			} else if (endUnitReg.test(borderRadius)) {
				// 判断字符串中是否以%、vw、vh、rem、em、px结尾，拼接上对应单位
				matchVal = matchVal * (hairline ? 2 : 1); // 如果是0.5px边框因为使用了scale(0.5)，要乘以2
				borderRadius = matchVal + borderRadius.match(endUnitReg)[0];
				// console.log("以特殊单位结尾按钮圆角", borderRadius);
			} else {
				// 只有纯数字的情况下，默认是rpx
				matchVal = uni.upx2px(matchVal) * (hairline ? 2 : 1); // 如果是0.5px边框因为使用了scale(0.5)，要乘以2
				borderRadius = matchVal + "px";
				// console.log("纯数字按钮圆角", borderRadius);
			}
			return borderRadius;
		},
	},
	created() {
		// 防抖点击事件
		this.debounceEmitClick = debounce(
			function() {
				this.$emit("click");
			},
			this.debounceTime,
			{ leading: this.debounceImmediate }
		);
		// 节流点击事件
		this.throttleEmitClick = throttle(
			function() {
				this.$emit("click");
			},
			this.throttleTime,
			{ leading: this.throttleImmediate }
		);
	},
	methods: {
		// 按钮点击事件
		handleBtnClick() {
			const { disabled } = this;
			// 按钮处于禁用状态就不执行任何操作
			if (disabled) return;
			// 判断是否开启按钮节流,开启节流走节流事件
			if (this.throttle) {
				this.throttleEmitClick();
			} else if (this.debounce) {
				this.debounceEmitClick();
			} else if (this.debounce && this.throttle) {
				this.debounceEmitClick();
			} else {
				this.$emit("click");
			}
		},
		// 按钮长按事件
		handleLongPress() {
			const { disabled } = this;
			// 按钮处于禁用状态就不执行任何操作
			if (disabled) return;
			this.$emit("longpress");
		},
	},
};
</script>

<style lang="scss" scoped>
.my-button {
	display: flex;
	align-items: center;
	justify-content: center;
	position: relative;
	/* #ifdef H5 */
	cursor: pointer;
	user-select: none;
	/* #endif */
	-webkit-appearance: none;

	&.box-shadow {
		box-shadow: 0 4rpx 8rpx rgba(5, 131, 248, 0.3);
	}

	// 1px边框
	&:not(.hairline)::after {
		position: absolute;
		top: 50%;
		left: 50%;
		box-sizing: border-box;
		width: 100%;
		height: 100%;
		content: " ";
		transform: translate(-50%, -50%);
		pointer-events: none;
		border-width: var(--btn-border-width, 1px);
		border-style: solid;
		border-color: var(--btn-border-color, rgba(0, 0, 0, 0));
		border-radius: var(--btn-border-radius, 0);
	}

	// 0.5px边框
	&.hairline::after {
		position: absolute;
		top: -50%;
		right: -50%;
		bottom: -50%;
		left: -50%;
		box-sizing: border-box;
		// width: auto;
		// height: auto;
		content: " ";
		transform: scale(0.5);
		pointer-events: none;
		border-width: var(--btn-border-width, 0);
		border-style: solid;
		border-color: var(--btn-border-color, rgba(0, 0, 0, 0));
		border-radius: var(--btn-border-radius, 0);
	}
}
</style>
